package com.zh.freechat.openfegin.grpc;

import com.google.protobuf.Empty;
import com.zh.freechat.domain.auth.LoginUser;
import com.zh.freechat.domain.chat.model.ChatMessage;
import com.zh.freechat.domain.message.repository.ChatMsgSendRecordRepository;
import com.zh.freechat.infrastructure.LoginAuthenticationApi;
import com.zh.mycommon.util.MyDateUtil;
import com.zh.mycommon.value.Tuple2;
import io.grpc.stub.StreamObserver;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import static com.zh.mycommon.viewdata.ToWrapper.foreach;

/**
 * @author Zhou
 * @date 13:23 2025/4/21
 */
@Slf4j
@AllArgsConstructor
@Component
public class ChatServiceProvider extends ChatServiceGrpc.ChatServiceImplBase {
    private ChatMsgSendRecordRepository chatMsgSendRecordRepository;

    @Override
    public void ping(Empty request, StreamObserver<Empty> responseObserver) {
        log.debug("rpc called ping() ...");
        // 发送响应消息
        responseObserver.onNext(Empty.getDefaultInstance());
        // 标记流结束
        responseObserver.onCompleted();
    }

    @Override
    public void verifyToken(ChatProto.TokenReq request, StreamObserver<ChatProto.UserResp> responseObserver) {
        log.debug("rpc called verifyToken() ...");

        var token = request.getToken();

        try {
            LoginUser loginUser = LoginAuthenticationApi.verifyToken(token);

            ChatProto.UserResp response = ChatProto.UserResp.newBuilder()
                    .setUid(loginUser.getUid())
                    .setUsername(loginUser.getUsername())
                    .addAllAuthorities(loginUser.getRoles()).build();
            // 发送响应消息
            responseObserver.onNext(response);
            // 标记流结束
            responseObserver.onCompleted();
        } catch (BadCredentialsException ex) {
            responseObserver.onError(ex);
        }
    }

    public static void main(String[] args) {
        var t = 1745994892276L;
        LocalDateTime dateTime = MyDateUtil.convertToLocalDateTime(t);
        System.out.println("dateTime = " + dateTime);

    }

    @Override
    public void getChatOfflineList(ChatProto.ChatMsgReq request, StreamObserver<ChatProto.ChatMsgListResp> responseObserver) {
        log.debug("rpc called getChatOfflineList() ... request={},", request.toString());

        long referenceTime = request.getReferenceTime();
        LocalDateTime dateTime = MyDateUtil.convertToLocalDateTime(referenceTime);

        var limit = 1000;
        List<Tuple2<ChatMessage, LocalDateTime>> chatMessages = chatMsgSendRecordRepository.selectOfflineRecordsByUserId(request.getUserId(), dateTime, limit);

        if (chatMessages.isEmpty()) {
            responseObserver.onNext(ChatProto.ChatMsgListResp.newBuilder().build());
            responseObserver.onCompleted(); // 标记流结束
            return;
        }

        var tailTime = chatMessages.getLast().v2();
        var protoMessages = foreach(chatMessages, t -> buildProtoMsg(t.v1())); //转换chatMessages

        var response = ChatProto.ChatMsgListResp.newBuilder()
                .setTailTime(MyDateUtil.toEpochMilli(tailTime))
                .addAllList(protoMessages)
                .build();
        // 发送响应消息
        responseObserver.onNext(response);
        // 标记流结束
        responseObserver.onCompleted();
    }

    protected ChatProto.ChatMsg buildProtoMsg(ChatMessage message) {
        // 先解析为 ZonedDateTime 对象，包含时区偏移信息
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(message.getCreateTime(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);

        return ChatProto.ChatMsg.newBuilder()
                .setIsGroup(message.getIsGroup())
                .setReceiver(message.getReceiver())
                .setSender(message.getSender())
                .setContent(message.getContent())
                .setType(message.getType())
                .setUrlRef(message.getUrlRef())
                .setIsNrt(true)
                .setChatId(message.getChatId())
                .setConvId(message.getConvId())
                .setId(message.getId())
                .setCreateTime(zonedDateTime.toInstant().toEpochMilli())
                .build();
    }

}
